package com.wyz.saas.common.view

import android.content.Context
import android.graphics.Rect
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.animation.AnticipateOvershootInterpolator
import android.view.animation.DecelerateInterpolator
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.annotation.AttrRes
import androidx.annotation.Nullable
import androidx.core.graphics.drawable.DrawableCompat
import com.wyz.saas.common.R
import com.wyz.saas.common.utils.UiTool


class AudioRecordView : FrameLayout, View.OnTouchListener {
    companion object {
        // 相关的结束方式
        // 结束是因为取消
        const val END_TYPE_CANCEL = 0

        // 正常结束
        const val END_TYPE_NONE = 1

        // 结束后想要播放
        const val END_TYPE_PLAY = 2

        // 结束后想要删除
        const val END_TYPE_DELETE = 3

        // 相关删除／播放按钮的透明度
        private const val MIN_ALPHA = 0.4f
    }

    // 回调的状态类
    interface Callback {
        // 请求开始录音
        fun requestStartRecord()

        // 请求结束录音，并携带结束标示
        fun requestStopRecord(type: Int)
    }

    // 触摸的点坐标
    private val mTouchPoint = FloatArray(2)

    // 播放的位置
    private val mPlayLocation: Rect = Rect()

    // 删除的位置
    private val mDeleteLocation: Rect = Rect()

    // 录制按钮的位置
    private val mRectLocation: Rect = Rect()

    // 浮动的录制按钮
    private var mRecordButton: ImageView? = null

    // 播放按钮和删除按钮
    private var mPlayButton: ImageView? = null

    private var mDeleteButton: ImageView? = null

    // 标示正在录制的状态
    private var mIsRecording = false

    // 回调方法
    private var mCallback: Callback? = null

    constructor(context: Context) : super(context)

    constructor(context: Context, @Nullable attrs: AttributeSet?) : super(context, attrs)

    constructor(
        context: Context,
        @Nullable attrs: AttributeSet?,
        @AttrRes defStyleAttr: Int
    ) : super(context, attrs, defStyleAttr)

    init {
        inflate(context, R.layout.view_audio_record, this)
        mRecordButton = findViewById(R.id.btn_record)
        mPlayButton = findViewById(R.id.im_play)
        mDeleteButton = findViewById(R.id.im_delete)
        mRecordButton?.setOnTouchListener(this)
        turnRecord()
    }

    /**
     * 初始化开始方法
     */
    fun setup(callback: Callback?) {
        mCallback = callback
    }

    override fun onLayout(
        changed: Boolean,
        left: Int,
        top: Int,
        right: Int,
        bottom: Int
    ) {
        super.onLayout(changed, left, top, right, bottom)
        // 当界面改变时得到对应的坐标位置
        mPlayLocation.left = mPlayButton!!.left - left
        mPlayLocation.top = mPlayButton!!.top - top
        mPlayLocation.right = mPlayButton!!.right - left
        mPlayLocation.bottom = mPlayButton!!.bottom - top

        mDeleteLocation.left = mDeleteButton!!.left - left
        mDeleteLocation.top = mDeleteButton!!.top - top
        mDeleteLocation.right = mDeleteButton!!.right - left
        mDeleteLocation.bottom = mDeleteButton!!.bottom - top

        mRectLocation.left = mRecordButton!!.left - left
        mRectLocation.top = mRecordButton!!.top - top
        mRectLocation.right = mRecordButton!!.right - left
        mRectLocation.bottom = mRecordButton!!.bottom - top
    }

    // 切换录音状态
    private fun turnRecord() {
        if (mIsRecording) {
            mPlayButton!!.animate()
                .alpha(MIN_ALPHA)
                .scaleX(1f)
                .scaleY(1f)
                .setDuration(320)
                .setInterpolator(AnticipateOvershootInterpolator())
                .start()
            mDeleteButton!!.animate()
                .alpha(MIN_ALPHA)
                .scaleX(1f)
                .scaleY(1f)
                .setDuration(320)
                .setInterpolator(AnticipateOvershootInterpolator())
                .start()
        } else {
            mPlayButton!!.animate()
                .alpha(0f)
                .scaleX(0f)
                .scaleY(0f)
                .setDuration(260)
                .setInterpolator(DecelerateInterpolator())
                .start()
            mDeleteButton!!.animate()
                .alpha(0f)
                .scaleX(0f)
                .scaleY(0f)
                .setDuration(260)
                .setInterpolator(DecelerateInterpolator())
                .start()
        }
    }

    // 当用户按下按钮时开始进行录音
    private fun onStart() {
        mIsRecording = true
        turnRecord()
        val callback = mCallback
        callback?.requestStartRecord()
    }

    // 当松开时结束
    private fun onStop(isCancel: Boolean) {
        if (!mIsRecording) return
        mIsRecording = false
        turnRecord()
        val callback = mCallback
        callback?.requestStopRecord(if (isCancel) END_TYPE_CANCEL else if (mActiveView == null) END_TYPE_NONE else if (mActiveView === mPlayButton) END_TYPE_PLAY else END_TYPE_DELETE)
    }

    // 监听用户的手指触摸，并相应对应的开始，停止，取消等操作
    override fun onTouch(v: View?, event: MotionEvent): Boolean {
        when (event.actionMasked) {
            MotionEvent.ACTION_MOVE -> {
                val pointX = event.x
                val pointY = event.y
                mTouchPoint[0] = pointX + mRectLocation.left
                mTouchPoint[1] = pointY + mRectLocation.top
                val inLeft = mTouchPoint[0] < mRectLocation.centerX()
                val rect = if (inLeft) mPlayLocation else mDeleteLocation
                val spaceLen: Double = calculatePointDistance(
                    mTouchPoint[0], mTouchPoint[1],
                    rect.centerX().toFloat(), rect.centerY().toFloat()
                )
                refreshAlpha(inLeft, spaceLen)
            }
            MotionEvent.ACTION_DOWN -> onStart()
            MotionEvent.ACTION_CANCEL -> onStop(true)
            MotionEvent.ACTION_UP -> onStop(false)
        }
        return false
    }

    // 计算两个点之间的距离
    private fun calculatePointDistance(
        px1: Float,
        py1: Float,
        px2: Float,
        py2: Float
    ): Double {
        val spaceX = Math.abs(px1 - px2).toDouble()
        val spaceY = Math.abs(py1 - py2).toDouble()
        return Math.sqrt(spaceX * spaceX + spaceY * spaceY)
    }

    // 记录最后一次的进度值，当进度值一致时不做刷新
    private var mLastProgress = 0f

    // 当前被激活的布局(播放，或者停止)
    private var mActiveView: View? = null

    // 根据手指滑动更改透明度
    private fun refreshAlpha(inLeft: Boolean, spaceLen: Double) {
        val rect = if (inLeft) mPlayLocation else mDeleteLocation
        val maxLen = calculatePointDistance(
            mRectLocation.centerX().toFloat(), mRectLocation.centerY().toFloat(),
            rect.centerX().toFloat(), rect.centerY().toFloat()
        )
        var progress = Math.round(spaceLen / maxLen * 1000) / 1000f
        if (mLastProgress == progress) return
        mLastProgress = progress
        Log.e("TAG", "mLastProgress:$mLastProgress")
        progress = 1 - Math.max(0f, Math.min(1f, progress))
        val touchPoint = mTouchPoint
        val overFlowIcon =
            rect.contains(touchPoint[0].toInt(), touchPoint[1].toInt())
        val activeView: ImageView
        val noneView: ImageView
        if (inLeft) {
            activeView = mPlayButton!!
            noneView = mDeleteButton!!
        } else {
            activeView = mDeleteButton!!
            noneView = mPlayButton!!
        }
        activeView.alpha = MIN_ALPHA + (1 - MIN_ALPHA) * progress
        val actionTintColor = if (overFlowIcon) UiTool.getColor(
            resources,
            R.color.colorAccent
        ) else UiTool.getColor(resources, R.color.textPrimary)
        DrawableCompat.setTint(activeView.drawable, actionTintColor)
        DrawableCompat.setTint(activeView.background, actionTintColor)
        noneView.alpha = MIN_ALPHA
        val noneTintColor = UiTool.getColor(resources, R.color.textPrimary)
        DrawableCompat.setTint(noneView.drawable, noneTintColor)
        DrawableCompat.setTint(noneView.background, noneTintColor)
        val scale = 1 + 0.2f * progress
        activeView.scaleX = scale
        activeView.scaleY = scale
        mActiveView = if (overFlowIcon) activeView else null
    }
}